﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Data.Objects;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Web.Mvc;
using Telerik.Web.Mvc;
using Transport.Areas.Administrator.Models;
using Transport.Core.Models.Parcels;
using Transport.Core.Models.Settings;
using Transport.Data;
using Transport.Infrastructure;
using Transport.Infrastructure.Mvc;
using Transport.Services;
using Transport.Services.Customers;
using Transport.Services.Infrastructure;
using Transport.Services.Parcels;
using Transport.Services.Settings;
using Telerik.Web.Mvc.Extensions;
using Transport.Services.Users;

namespace Transport.Areas.Administrator.Controllers
{
    [Authorize]
    public class ParcelController : ControllerBase<IParcelRepository, Parcel>
    {
        private readonly IStateProvinceRepository _stateProvinceRepository;
        private readonly ICustomerRepository _customerRepository;
        private readonly IParcelService _parcelService;
        private readonly ITrackingRepository _trackingRepository;
        private readonly IMyOfficeRepository _myOfficeRepository;
        private readonly IParcelRepository _parcelRepository;
        private const string CustomerId = "CUSTOMER_ID";
        private readonly IStateProvinceBelongToRegionRepository _stateProvinceBelongToRegionRepository;
        private readonly IRegionRepository _regionRepository;
        private readonly IParcelDeliveryService _parcelDeliveryService;
        private readonly IParcelPackagingGroupRepository _parcelPackagingGroupRepository;
        private readonly IParcelPackagingItemRepository _parcelPackagingItemRepository;
        private readonly IUserRepository _userRepository;

        public ParcelController(IUnitOfWork unitOfWork, IParcelRepository repository,
                                IStateProvinceRepository stateProvinceRepository, ICustomerRepository customerRepository,
                                IParcelService parcelService, ITrackingRepository trackingRepository,
                                IMyOfficeRepository myOfficeRepository, IParcelRepository parcelRepository,
                                IStateProvinceBelongToRegionRepository stateProvinceBelongToRegionRepository,
                                IRegionRepository regionRepository, IParcelDeliveryService parcelDeliveryService,
                                IParcelPackagingGroupRepository parcelPackagingGroupRepository,
                                IParcelPackagingItemRepository parcelPackagingItemRepository,
                                IUserRepository userRepository)
            : base(repository, unitOfWork)
        {
            _stateProvinceRepository = stateProvinceRepository;
            _customerRepository = customerRepository;
            _parcelService = parcelService;
            _trackingRepository = trackingRepository;
            _myOfficeRepository = myOfficeRepository;
            _parcelRepository = parcelRepository;
            _stateProvinceBelongToRegionRepository = stateProvinceBelongToRegionRepository;
            _regionRepository = regionRepository;
            _parcelDeliveryService = parcelDeliveryService;
            _parcelPackagingGroupRepository = parcelPackagingGroupRepository;
            _parcelPackagingItemRepository = parcelPackagingItemRepository;
            _userRepository = userRepository;
        }
        //
        // GET: /Administrator/Parcel/

        public ActionResult Index()
        {
            return View();
        }

        [GridAction]
        public ActionResult GridModel(string search)
        {
            var query = from x in Repository.Search(search).Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        where x.MyOfficeId == WorkContext.MyOfficeId
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            TotalCost = x.TotalCost,
                            TotalWeight = x.TotalWeight
                        };
            var gridModel = new GridModel<ParcelModel>
            {
                Data = query
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        [GridAction]
        public ActionResult GetTrackings(int parcelId)
        {
            var query = from x in _trackingRepository.GetAll().Include(p => p.Parcel)
                        join o in _stateProvinceRepository.GetAll() on x.Parcel.DeliverFromId equals o.StateProvinceId
                        where x.ParcelId == parcelId
                        select new TrackingModel
                        {
                            DateOfSending = x.DateOfSending,
                            TrackingId = x.TrackingId,
                            DeliverToName = o.StateProvinceName,
                            Status = x.Status,
                            TrackingNumbers = x.Parcel.TrackingNumbers
                        };

            var gridModel = new GridModel<TrackingModel>
            {
                Data = query.ToList()
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult Create()
        {
            var stateProvinces = _stateProvinceRepository.Search("").ToList();
            var customers = _customerRepository.Search(string.Empty).Where(p => p.MyOfficeId == WorkContext.MyOfficeId).ToList();
            var offices = _myOfficeRepository.Search("").ToList();
            var myProvince = stateProvinces.FirstOrDefault(p => p.IsMain && p.MyOfficeId == WorkContext.MyOfficeId);
            if (myProvince==null)
            {
                SetErrorNotification("Chọn tỉnh thành trực thuộc cho trung tâm này.");
                return RedirectToAction("Index", new { area = "Administrator" });
            }
            
            var customerCode = string.Empty;
            var customerId = 0;
            if (Session[CustomerId] != null)
            {
                customerId = int.Parse(Session[CustomerId].ToString());
                customerCode = customers.Where(p => p.CustomerId == customerId).Select(p => p.CustomerCode).FirstOrDefault();
                
            }
            var model = new ParcelModel
            {
                DeliverFromId = myProvince.StateProvinceId,
                DeliverFromName = myProvince.StateProvinceName,
                StateProvincesFrom = stateProvinces.Where(p => p.MyOfficeId == WorkContext.MyOfficeId).Select(t => new GroupedSelectListItem
                {
                    GroupKey = t.MyOfficeId.ToString(),
                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                    Text = t.StateProvinceName,
                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                }).OrderBy(p => p.Text).ToList(),
                Customers = customers,
                DateOfSending = DateTime.Now,
                IsHandInput = false,
                PaymentType = (int) PaymentTypes.EnumPaymentTypes.Debt,
                CustomerCode = customerCode,
                CustomerId = customerId,
                StateProvincesTo = stateProvinces.Select(t => new GroupedSelectListItem
                {
                    GroupKey = t.MyOfficeId.ToString(),
                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                    Text = t.StateProvinceName,
                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                }).OrderBy(p => p.Text).ToList()
            };

            return View(model);
        }

        public virtual ActionResult Edit(int id)
        {
            var entity = Repository.GetById(id);
            if (entity==null)
            {
                SetErrorNotification("Bưu phẩm này không tồn tại.");
                return RedirectToAction("Index", new { area = "Administrator" });
            }
            var stateProvinces = _stateProvinceRepository.Search("").ToList();
            var customers = _customerRepository.Search("").Where(p => p.MyOfficeId == WorkContext.MyOfficeId).ToList();
            var offices = _myOfficeRepository.Search("").ToList();
            var myProvince = stateProvinces.FirstOrDefault(p => p.IsMain && p.MyOfficeId == WorkContext.MyOfficeId);
            if (myProvince == null)
            {
                SetErrorNotification("Chọn tỉnh thành trực thuộc cho trung tâm này.");
                return RedirectToAction("Index", new { area = "Administrator" });
            }
            var model = new ParcelModel
                            {
                                StateProvincesFrom = stateProvinces.Select(t => new GroupedSelectListItem
                                {
                                    GroupKey = t.MyOfficeId.ToString(),
                                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                                    Text = t.StateProvinceName,
                                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                                }).ToList(),
                                Customers = customers,
                                CustomerId = entity.CustomerId.HasValue ? entity.CustomerId.Value : 0,
                                CustomerCode = entity.CustomerId.HasValue ? entity.Customer.CustomerCode : string.Empty,
                                DateOfSending = entity.DateOfSending,
                                DeliverFromId = entity.DeliverFromId,
                                DeliverFromName = myProvince.StateProvinceName,
                                ParcelId = entity.ParcelId,
                                PaymentType = entity.PaymentType,
                                DeliverToId = entity.DeliverToId,
                                ToAddress = entity.ToAddress,
                                TotalCost = entity.TotalCost,
                                TotalCostHidden = entity.TotalCost,
                                TotalWeight = entity.TotalWeight,
                                TrackingNumbers = entity.TrackingNumbers,
                                IsHandInput = entity.IsHandInput,
                                Receiver = entity.Receiver,
                                Collected = entity.Collected,
                                IsApproval = entity.IsApproval,
                                Note = entity.Note,
                                StateProvincesTo = stateProvinces.Select(t => new GroupedSelectListItem
                                {
                                    GroupKey = t.MyOfficeId.ToString(),
                                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                                    Text = t.StateProvinceName,
                                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                                }).ToList()
                            };
            return View("Edit", model);
        }

        [HttpPost, ValidateInput(false)]
        public virtual ActionResult Save(ParcelModel parcelModel)
        {
            if (!ModelState.IsValid)
            {
                var stateProvinces = _stateProvinceRepository.Search("").ToList();
                var customers = _customerRepository.Search("").Where(p => p.MyOfficeId == WorkContext.MyOfficeId).ToList();
                var offices = _myOfficeRepository.Search("").ToList();
                parcelModel.StateProvincesTo = stateProvinces.Select(t => new GroupedSelectListItem
                {
                    GroupKey = t.MyOfficeId.ToString(),
                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                    Text = t.StateProvinceName,
                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                }).ToList();
                parcelModel.StateProvincesFrom = stateProvinces.Where(p => p.MyOfficeId == WorkContext.MyOfficeId).Select(t => new GroupedSelectListItem
                {
                    GroupKey = t.MyOfficeId.ToString(),
                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                    Text = t.StateProvinceName,
                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                }).ToList();
                parcelModel.Customers = customers;
                parcelModel.TotalCost = parcelModel.TotalCostHidden;
                //parcelModel.PostOffices = new List<Core.Models.Settings.PostOffice>();
                return View("Create", parcelModel);
            }
            //Check existed
            var modelExisted = Repository.GetAll().FirstOrDefault(p => p.TrackingNumbers == parcelModel.TrackingNumbers);
            if ((modelExisted != null && modelExisted.ParcelId != parcelModel.ParcelId) || (modelExisted != null && parcelModel.ParcelId <= 0))
            {
                SetErrorNotification("Số vận đơn này đã tồn tại trong hệ thống.");
                var stateProvinces = _stateProvinceRepository.Search("").ToList();
                var customers = _customerRepository.Search("").Where(p => p.MyOfficeId == WorkContext.MyOfficeId).ToList();
                var offices = _myOfficeRepository.Search("").ToList();
                parcelModel.StateProvincesFrom = stateProvinces.Where(p => p.MyOfficeId == WorkContext.MyOfficeId).Select(t => new GroupedSelectListItem
                {
                    GroupKey = t.MyOfficeId.ToString(),
                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                    Text = t.StateProvinceName,
                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                }).ToList();
                parcelModel.Customers = customers;
                parcelModel.TotalCost = parcelModel.TotalCostHidden;
                parcelModel.StateProvincesTo = stateProvinces.Select(t => new GroupedSelectListItem
                {
                    GroupKey = t.MyOfficeId.ToString(),
                    GroupName = offices.FirstOrDefault(p => p.MyOfficeId == t.MyOfficeId).OfficeName,
                    Text = t.StateProvinceName,
                    Value = t.StateProvinceId.ToString(CultureInfo.InvariantCulture)
                }).ToList();
                if (parcelModel.CustomerId > 0)
                {
                    parcelModel.CustomerCode = customers.Where(p => p.CustomerId == parcelModel.CustomerId).Select(p => p.CustomerCode).FirstOrDefault();

                }
                return View("Create", parcelModel);
            }
            if (parcelModel.ParcelId <= 0) //Create
            {
                var parcel = new Parcel
                                 {
                    CreateDate = DateTime.Now,
                    DateOfSending = parcelModel.DateOfSending,
                    IsDeleted = false,
                    DeliverFromId = parcelModel.DeliverFromId,
                    PaymentType = parcelModel.PaymentType,
                    DeliverToId = parcelModel.DeliverToId,
                    ToAddress = parcelModel.ToAddress,
                    TotalCost = parcelModel.TotalCostHidden,
                    TotalWeight = parcelModel.TotalWeight,
                    TrackingNumbers = parcelModel.TrackingNumbers.Trim(),
                    IsHandInput = parcelModel.IsHandInput,
                    Trackings = new List<Tracking>(),
                    Status = (int)TrackingStatus.EnumTrackingStatus.Import,
                    MyOfficeId = WorkContext.MyOfficeId,
                    Note = parcelModel.Note
                };
                //Add default tracking
                var tracking = new Tracking
                                   {
                    CreateDate = DateTime.Now,
                    DateOfSending = parcelModel.DateOfSending,
                    IsDeleted = false,
                    StateProvinceId = parcelModel.DeliverFromId,
                    Status = (int)TrackingStatus.EnumTrackingStatus.Import,
                    UserId = WorkContext.CurrentUserId
                };
                parcel.Trackings.Add(tracking);
                //Add customer
                if (parcelModel.CustomerId > 0)
                {
                    parcel.CustomerId = parcelModel.CustomerId;
                }
                else
                {
                    parcel.CustomerId = null;
                }
                using (UnitOfWork)
                {
                    Repository.Insert(parcel);
                }
                //Remember customer ID
                Session[CustomerId] = parcelModel.CustomerId;
                //Save success
                SetSuccessNotification(string.Format("{0} đã được lưu thành công.", "Bưu phẩm"));
                return RedirectToAction("Create", new { area = "Administrator" });
            }
            else //Edit
            {
                var parcel = Repository.GetById(parcelModel.ParcelId);
                parcel.DateOfSending = parcelModel.DateOfSending;
                parcel.DeliverFromId = parcelModel.DeliverFromId;
                parcel.PaymentType = parcelModel.PaymentType;
                parcel.DeliverToId = parcelModel.DeliverToId;
                parcel.ToAddress = parcelModel.ToAddress;
                parcel.TotalCost = parcelModel.TotalCostHidden;
                parcel.TotalWeight = parcelModel.TotalWeight;
                parcel.TrackingNumbers = parcelModel.TrackingNumbers.Trim();
                parcel.IsHandInput = parcelModel.IsHandInput;
                parcel.Note = parcelModel.Note;

                //Duyệt giá - Xác nhận thu tiền
                if (WorkContext.Roles.Contains(RoleType.KTTruong))
                {
                    parcel.IsApproval = parcelModel.IsApproval;
                    parcel.Collected = parcelModel.Collected;
                }

                //Update default tracking
                var importStatus = (int)TrackingStatus.EnumTrackingStatus.Import;
                var defaultTracking = parcel.Trackings.FirstOrDefault(p => p.Status == importStatus);
                defaultTracking.DateOfSending = parcelModel.DateOfSending;
                //Update customer
                if (parcelModel.CustomerId > 0)
                {
                    parcel.CustomerId = parcelModel.CustomerId;
                }
                else
                {
                    parcel.CustomerId = null;
                }
                using (UnitOfWork)
                {
                    Repository.Update(parcel);
                }
            }

            //Save success
            SetSuccessNotification(string.Format("{0} đã được lưu thành công.", "Bưu phẩm"));
            if (WorkContext.Roles.Contains(RoleType.KTTruong))
            {
                return RedirectToAction("Collected", "Parcel", new { area = "Administrator" });
            }
            return RedirectToAction("Index", "Tracking", new { area = "Administrator" });
        }

        public ActionResult Delete(int id)
        {
            try
            {
                using (UnitOfWork)
                {
                    Repository.Delete(id);
                }
                SetSuccessNotification("Bưu phẩm đã được xóa thành công.");
            }
            catch
            {
                SetErrorNotification("Bưu phẩm này không thể xóa, vì đã được sử dụng!");
            }
            return RedirectToAction("index", "Tracking", new { area = "Administrator" });
        }

        public ActionResult GetCost(int deliverFromId, int deliverToId, int totalWeight, int customerId)
        {
            return Json(_parcelService.GetCost(deliverFromId, deliverToId, totalWeight, customerId, WorkContext.MyOfficeId));
        }

        public ActionResult DownloadParcelAsPdf()
        {
            var fileName = string.Format("pdfcatalog_{0}.pdf", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
            return PdfResult(_parcelService.CreatePpf("Le Quang Nguyen"),fileName);
        }

        public ActionResult GetCustomer(string customerCode)
        {
            return Json(_customerRepository.Search("").Where(p => p.CustomerCode == customerCode).Select(p => p.CustomerId));
        }

        #region Duyệt và xác nhận giá
        public virtual ActionResult VerifyCost()
        {
            return View(new VerifyCostModel());
        }

        [HttpPost]
        public virtual ActionResult VerifyCost(VerifyCostModel verifyCost)
        {
            //Check existed
            var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == verifyCost.TrackingNumbers);
            if (parcel == null)
            {
                SetErrorNotification("Số vận đơn này không tồn tại trong hệ thống.");
                return View(verifyCost);
            }
            else if(parcel.IsApproval)
            {
                SetErrorNotification("Số vận đơn này đã được duyệt.");
                return View(verifyCost);
            }
            using (UnitOfWork)
            {
                parcel.IsApproval = true;
                parcel.ApprovalBy = WorkContext.CurrentUserId;
                parcel.ApprovalDate = DateTime.Now;

                parcel.PaymentType = verifyCost.PaymentType;
                parcel.TotalCost = verifyCost.TotalCostHidden;
                parcel.TotalWeight = verifyCost.TotalWeight;
                parcel.IsHandInput = verifyCost.IsHandInput;

                _parcelRepository.Update(parcel);

            }
            //Save success
            SetSuccessNotification(string.Format("{0} đã được duyệt.", "Bưu phẩm"));
            return RedirectToAction("VerifyCost", new { area = "Administrator" });
        }

        public virtual ActionResult GetParcelForVerifyCost(string trackingNumbers)
        {
            var parcel = _parcelRepository.GetAll().Include(p => p.Customer).FirstOrDefault(p => p.TrackingNumbers == trackingNumbers);
            if (parcel == null)
            {
                return Json(false);
            }
            var model = new VerifyCostModel
            {
                TrackingNumbers = parcel.TrackingNumbers,
                TotalWeight = parcel.TotalWeight,
                TotalCost = parcel.TotalCost,
                TotalCostHidden = parcel.TotalCost,
                PaymentType = parcel.PaymentType,
                IsHandInput = parcel.IsHandInput,
                DeliverFromId = parcel.DeliverFromId,
                DeliverToId = parcel.DeliverToId,
                CustomerId = parcel.CustomerId,
                CustomerCode = parcel.CustomerId.HasValue ? parcel.Customer.CustomerCode : string.Empty,
                CustomerName = parcel.CustomerId.HasValue ? parcel.Customer.CustomerName : "Khách lẻ"
            };
            return Json(RenderPartialViewToString("_VerifyCostDetail", model));
        }

        public ActionResult NotVerifyCostYet()
        {
            return View();
        }

        [GridAction]
        public ActionResult NotVerifyCostYetGridModel(string search)
        {
            var query = from x in Repository.Search(search).Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        where x.MyOfficeId == WorkContext.MyOfficeId
                        && !x.IsApproval
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            TotalCost = x.TotalCost,
                            TotalWeight = x.TotalWeight
                        };
            var gridModel = new GridModel<ParcelModel>
            {
                Data = query
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }
        #endregion

        #region Xác Nhận Thu Tiền
        public ActionResult Collected()
        {
            return View();
        }

        [GridAction]
        public ActionResult CollectedGridModel(string search, bool isApproval, bool isCollected, string filter, GridCommand command)
        {
            //Hiện các bưu phẩm trong bưu cục và bưu phẩm được chuyển từ bưu cục khác đến
            var query = from x in Repository.Search(search).Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        where (x.MyOfficeId == WorkContext.MyOfficeId || x.DeliverToOfficeId == WorkContext.MyOfficeId)
                        && ((!x.Collected && isCollected) || isCollected == false)
                        && ((!x.IsApproval && isApproval) || isApproval == false)
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            TotalCost = x.TotalCost,
                            TotalWeight = x.TotalWeight,
                            Collected = x.Collected,
                            PaymentType = x.PaymentType
                        };
            GridModel<ParcelModel> gridModel;
            var hasFilterByPaymentTypeName = !string.IsNullOrEmpty(filter) && filter.Contains("PaymentTypeName");
            if (hasFilterByPaymentTypeName)
            {
                gridModel = new GridModel<ParcelModel>
                {
                    Data = query.ToList()
                };
            }
            else
            {
                gridModel = new GridModel<ParcelModel>
                {
                    Data = query,
                };
            }
            if (command.FilterDescriptors.Any())
            {
                query = query.ToList().AsQueryable();
            }
            double total = 0;
            try
            {
                total = Convert.ToDouble(query.Where(command.FilterDescriptors).Sum("TotalCost"));
            }
            catch
            {
            }
            Session["totalcost"] = String.Format("{0:0,0}", total);
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult GetTotalCostOfLisst()
        {
            return Json(Session["totalcost"]);
        }

        [HttpPost]
        public virtual ActionResult SetCollected(int parcelId)
        {
            //Check existed
            var parcel = _parcelRepository.GetById(parcelId);
            if (parcel == null)
            {
                SetErrorNotification("Số vận đơn này không tồn tại trong hệ thống.");
                return Json(false);
            }
            using (UnitOfWork)
            {
                parcel.Collected = true;
                _parcelRepository.Update(parcel);

            }
            //Save success
            return Json(true);
        }
        #endregion

        #region Chia Thùng

        public ActionResult Split()
        {
            return View();
        }

        [GridAction]
        public ActionResult SplitGridModel(string search)
        {
            if (!string.IsNullOrEmpty(search))
            {
                var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == search);
                var myProvince = _stateProvinceRepository.Search("").FirstOrDefault(p => p.IsMain && p.MyOfficeId == WorkContext.MyOfficeId);
                //Nếu bưu phẩm có trạng thái nhỏ hơn Khai Thác
                if (parcel != null && (parcel.Status < (int)TrackingStatus.EnumTrackingStatus.Extraction))
                {
                    var tracking = new Tracking
                    {
                        CreateDate = DateTime.Now,
                        DateOfSending = DateTime.Now,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId,
                        StateProvinceId = myProvince.StateProvinceId,
                        Status = (int)TrackingStatus.EnumTrackingStatus.Extraction,
                        UserId = WorkContext.CurrentUserId
                    };
                    using (UnitOfWork)
                    {
                        _trackingRepository.Insert(tracking);
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Extraction;
                        _parcelRepository.Update(parcel);
                    }
                }
            }
            //Hiển thị bưu phẩm ở trạng thái Nhập Hệ Thống
            var query = from x in Repository.GetAll().Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        join r in _stateProvinceBelongToRegionRepository.GetAll().Include(p => p.Region) on x.DeliverToId equals r.StateProvinceId
                        where x.MyOfficeId == WorkContext.MyOfficeId
                        && r.MyOfficeId == WorkContext.MyOfficeId
                        && x.Status == (int)TrackingStatus.EnumTrackingStatus.Import
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            RegionName = r.Region.RegionName,
                            IsEms = x.IsEms
                        };
            var gridModel = new GridModel<ParcelModel>
            {
                Data = query
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult GetDelivery(string search)
        {
            if (!string.IsNullOrEmpty(search))
            {
                //Tìm kiếm bưu phẩm thuộc Thùng nào
                var data = (from x in Repository.GetAll()
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        join r in _stateProvinceBelongToRegionRepository.GetAll().Include(p => p.Region) on x.DeliverToId equals r.StateProvinceId
                        where (x.MyOfficeId == WorkContext.MyOfficeId || x.DeliverToOfficeId == WorkContext.MyOfficeId)
                        && r.MyOfficeId == WorkContext.MyOfficeId
                        && x.TrackingNumbers == search
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            DeliverToName = p.StateProvinceName,
                            RegionName = r.Region.RegionName,
                            IsEms = x.IsEms
                        }).FirstOrDefault();
                if (data != null)
                {
                    return Json(data);
                }
            }
            return Json(new ParcelModel 
            {
                ParcelId = 0,
                TrackingNumbers = "Không tìm thấy!",
                DeliverToName = "",
                RegionName = "",
                IsEms = false
            });
        }

        [HttpPost]
        public ActionResult SetNgoaiThuyen(string trackingNumbers)
        {
            if (!string.IsNullOrEmpty(trackingNumbers))
            {
                var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == trackingNumbers);
                if (parcel != null)
                {
                    using (UnitOfWork)
                    {
                        parcel.IsEms = !parcel.IsEms;
                        _parcelRepository.Update(parcel);
                    }
                    return Json(true);
                }
            }
            return Json(false);
        }

        #endregion

        #region Đóng Gói - Chuyển Tiếp

        public ActionResult Packaging()
        {
            return View();
        }

        [GridAction]
        public ActionResult PackagingGridModel(string search)
        {
            var model = _regionRepository.Search(search).Where(p => p.MyOfficeId == WorkContext.MyOfficeId).ToList();
            string ngoaiTuyen = "Ngoại Tuyến";
            if (string.IsNullOrEmpty(search) || ngoaiTuyen.ToLower().Contains(search.ToLower()))
            {
                model.Add(new Region
                {
                    RegionId = -1,
                    RegionName = ngoaiTuyen
                });
            }

            var gridModel = new GridModel<RegionModel>
            {
                Data = model.Select(x => new RegionModel
                {
                    RegionId = x.RegionId,
                    RegionName = x.RegionName
                })
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult PackagingByRegion(int id)
        {
            if (id <= 0)
            {
                return View(new RegionModel()
                {
                    RegionName = "Ngoại Tuyến",
                    RegionId = -1
                });
            }
            var region = _regionRepository.GetAll().FirstOrDefault(p => p.MyOfficeId == WorkContext.MyOfficeId && p.RegionId == id);
            var model = new RegionModel()
            {
                RegionName = region.RegionName,
                RegionId = region.RegionId
            };
            return View(model);
        }

        [GridAction]
        public ActionResult GridPackagingByRegionModel(string search, int id)
        {
            IQueryable<ParcelPackagingGroupModel> users;
            if (id <= 0)
            {
                users = from x in _parcelPackagingGroupRepository.Search(search)
                        join u in _userRepository.GetAll() on x.CreateUserId equals u.UserId
                        where !x.RegionId.HasValue && x.MyOfficeId == WorkContext.MyOfficeId
                        select new ParcelPackagingGroupModel()
                        {
                            CreateDate = x.CreateDate,
                            ParcelPackagingGroupId = x.ParcelPackagingGroupId,
                            CreateUser = u.FirstName + u.LastName
                        };
            }
            else
            {
                users = from x in _parcelPackagingGroupRepository.Search(search)
                        join u in _userRepository.GetAll() on x.CreateUserId equals u.UserId
                        where x.RegionId == id && x.MyOfficeId == WorkContext.MyOfficeId
                        select new ParcelPackagingGroupModel()
                        {
                            CreateDate = x.CreateDate,
                            ParcelPackagingGroupId = x.ParcelPackagingGroupId,
                            CreateUser = u.FirstName + u.LastName
                        };
            }

            var gridModel = new GridModel<ParcelPackagingGroupModel>
            {
                Data = users
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        [GridAction]
        public ActionResult ParcelNotPackagingGridModel(int id)
        {
            IQueryable<ParcelModel> query;
            //Hiển thị cho thùng Ngoại Tuyến
            if (id <=0)
            {
                query = from x in Repository.GetAll().Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        join r in _stateProvinceBelongToRegionRepository.GetAll().Include(p => p.Region) on x.DeliverToId equals r.StateProvinceId
                        where ((x.MyOfficeId == WorkContext.MyOfficeId && x.Status == (int)TrackingStatus.EnumTrackingStatus.Extraction)
                        || (x.DeliverToOfficeId == WorkContext.MyOfficeId && x.Status == (int)TrackingStatus.EnumTrackingStatus.ComePostOffices))
                        && r.MyOfficeId == WorkContext.MyOfficeId
                        && x.IsEms
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerShortName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            RegionName = r.Region.RegionName,
                            IsEms = x.IsEms,
                            ToAddress = x.ToAddress
                        };
            }
            else
            {
                //Hiển thị bưu phẩm theo thùng
                //Chỉ hiển thị trạng thái là Khai Thác
                //hoặc trạng thái Đã Đến Bưu Cục nếu bưu phẩm đó được chuyển tới bưu cục khác
                query = from x in Repository.GetAll().Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        join r in _stateProvinceBelongToRegionRepository.GetAll().Include(p => p.Region) on x.DeliverToId equals r.StateProvinceId
                        where ((x.MyOfficeId == WorkContext.MyOfficeId && x.Status == (int)TrackingStatus.EnumTrackingStatus.Extraction)
                        || (x.DeliverToOfficeId == WorkContext.MyOfficeId && x.Status == (int)TrackingStatus.EnumTrackingStatus.ComePostOffices))
                        && r.MyOfficeId == WorkContext.MyOfficeId
                        && r.RegionId == id
                        && !x.IsEms
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerShortName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            RegionName = r.Region.RegionName,
                            IsEms = x.IsEms,
                            ToAddress = x.ToAddress
                        };
            }
            var gridModel = new GridModel<ParcelModel>
            {
                Data = query
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult CreatePackaging(int id)
        {
            ParcelPackagingGroup entity;
            if (id <= 0)
            {
                entity = new ParcelPackagingGroup()
                {
                    CreateDate = DateTime.Now,
                    CreateUserId = WorkContext.CurrentUserId,
                    IsDeleted = false,
                    MyOfficeId = WorkContext.MyOfficeId,
                    ParcelPackagingItems = new List<ParcelPackagingItem>()
                };
            }
            else
            {
                entity = new ParcelPackagingGroup()
                {
                    CreateDate = DateTime.Now,
                    CreateUserId = WorkContext.CurrentUserId,
                    IsDeleted = false,
                    MyOfficeId = WorkContext.MyOfficeId,
                    ParcelPackagingItems = new List<ParcelPackagingItem>(),
                    RegionId = id
                };
            }
            
            using (UnitOfWork)
            {
                _parcelPackagingGroupRepository.Insert(entity);
            }

            return RedirectToAction("EditPackaging", new { id = entity.ParcelPackagingGroupId });
        }

        public ActionResult EditPackaging(int id)
        {
            var entity = _parcelPackagingGroupRepository.GetById(id);
            var model = new ParcelPackagingGroupModel()
            {
                CreateDate = entity.CreateDate,
                ParcelPackagingGroupId = entity.ParcelPackagingGroupId,
                RegionName = entity.RegionId.HasValue ? entity.Region.RegionName : "Ngoại Tuyến",
                RegionId = entity.RegionId.HasValue ? entity.Region.RegionId : -1
            };
            return View(model);
        }

        [GridAction]
        public ActionResult GridPackagingItemModel(string search, int id)
        {
            var data = from x in _parcelPackagingItemRepository.Search(string.Empty).Include(p => p.Parcel.Customer)
                       join s in _stateProvinceRepository.GetAll() on x.Parcel.DeliverToId equals s.StateProvinceId
                       where x.ParcelPackagingGroupId == id
                       select new ParcelPackagingItemModel
                       {
                           DateOfSending = x.Parcel.DateOfSending,
                           ToAddress = x.Parcel.ToAddress,
                           TrackingNumbers = x.Parcel.TrackingNumbers,
                           TotalWeight = x.Parcel.TotalWeight,
                           ParcelId = x.ParcelId,
                           CustomerId = x.Parcel.CustomerId,
                           CustomerName = x.Parcel.Customer.CustomerName,
                           DeliverToName = s.StateProvinceName,
                           ParcelPackagingItemId = x.ParcelPackagingItemId,
                           TotalCost = x.Parcel.PaymentType == (int)PaymentTypes.EnumPaymentTypes.Collection ? x.Parcel.TotalCost : 0,
                            Note = x.Parcel.Note
                       };

            var gridModel = new GridModel<ParcelPackagingItemModel>
            {
                Data = data
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult DeletePackagingItem(int id)
        {
            int parcelPackagingGroupId = 0;
            try
            {
                var parcelPackagingItem = _parcelPackagingItemRepository.GetById(id);
                parcelPackagingGroupId = parcelPackagingItem.ParcelPackagingGroupId;
                var parcel = _parcelRepository.GetById(parcelPackagingItem.ParcelId);
                if (parcel.Status > (int) TrackingStatus.EnumTrackingStatus.BeForwarding)
                {
                    SetErrorNotification("Bill này không thể xóa!");
                    return RedirectToAction("EditPackaging", "Parcel", new { id = parcelPackagingGroupId, area = "Administrator" });
                }
                using (UnitOfWork)
                {
                    var trackings = _trackingRepository.GetAll().Where(p => p.ParcelId == parcelPackagingItem.ParcelId && (p.Status == (int)TrackingStatus.EnumTrackingStatus.Packaging || p.Status == (int)TrackingStatus.EnumTrackingStatus.BeForwarding));
                    foreach (var tracking in trackings)
                    {
                        tracking.IsDeleted = true;
                    }
                    parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Extraction;
                    _parcelRepository.Update(parcel);
                    _parcelPackagingItemRepository.Delete(id);
                }
                SetSuccessNotification("Bill đã được xóa thành công.");
            }
            catch
            {
                SetErrorNotification("Bill này không thể xóa, vì đã được sử dụng!");
            }
            return RedirectToAction("EditPackaging", "Parcel", new { id = parcelPackagingGroupId, area = "Administrator" });
        }
        public ActionResult PackagingToGroup(string search, int id)
        {
            if (!string.IsNullOrEmpty(search))
            {
                var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == search);
                //Nếu là bưu phẩm ở trạng thái khai thác (sau khi chia thùng)
                //Nếu là bưu phẩm ở trạng thái là đến bưu cục (dành cho các bưu phẩm chuyển bưu cục để phát)
                if (parcel != null && (parcel.Status == (int)TrackingStatus.EnumTrackingStatus.Extraction
                    || parcel.Status == (int)TrackingStatus.EnumTrackingStatus.ComePostOffices))
                {
                    if (id > 0)
                    {
                        var group = _parcelPackagingGroupRepository.GetById(id);
                        //Nếu là Thùng Ngoại Tuyến
                        if(!group.RegionId.HasValue)
                        {
                            //Nếu là Thùng Ngoại Tuyến và bưu phẩm không phải là ngoại tuyến
                            if (!parcel.IsEms)
                            {
                                return Json(false);
                            }
                        }
                        else
                        {
                            //Nếu bưu phẩm phải là ngoại tuyến
                            if (parcel.IsEms)
                            {
                                return Json(false);
                            }
                            //Nếu bưu phẩm đang đóng gói không nằm trong thùng được chia
                            var packagingValid = _stateProvinceBelongToRegionRepository.GetAll().Any(p => p.RegionId == group.RegionId && p.StateProvinceId == parcel.DeliverToId);
                            if (!packagingValid)
                            {
                                return Json(false);
                            }
                        }
                    }
                    var myProvince = _stateProvinceRepository.Search("").FirstOrDefault(p => p.IsMain && p.MyOfficeId == WorkContext.MyOfficeId);
                    var tracking = new Tracking
                    {
                        CreateDate = DateTime.Now,
                        DateOfSending = DateTime.Now,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId,
                        StateProvinceId = myProvince.StateProvinceId,
                        Status = (int)TrackingStatus.EnumTrackingStatus.Packaging,
                        UserId = WorkContext.CurrentUserId
                    };
                    var trackingBeForwarding = new Tracking
                    {
                        CreateDate = DateTime.Now,
                        DateOfSending = DateTime.Now,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId,
                        StateProvinceId = myProvince.StateProvinceId,
                        Status = (int)TrackingStatus.EnumTrackingStatus.BeForwarding,
                        UserId = WorkContext.CurrentUserId
                    };

                    var parcelPackaging = new ParcelPackagingItem()
                    {
                        CreateDate = DateTime.Now,
                        ParcelPackagingGroupId = id,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId
                    };
                    using (UnitOfWork)
                    {
                        _parcelPackagingItemRepository.Insert(parcelPackaging);
                        _trackingRepository.Insert(tracking);
                        _trackingRepository.Insert(trackingBeForwarding);
                        //nếu bưu phẩm là ngoại tuyến
                        //bưu phẩm ở trạng thái khai thác
                        //thì bưu phẩm không cần phải chuyển bưu cục khác
                        if (parcel.IsEms && parcel.Status == (int)TrackingStatus.EnumTrackingStatus.Extraction)
                        {
                            parcel.DeliverToOfficeId = WorkContext.MyOfficeId;
                        }
                        else
                        {
                            //Get the office that parcel will be delivery to
                            var deliveryToOffice = _stateProvinceRepository.GetAll()
                                .Where(p => p.StateProvinceId == parcel.DeliverToId)
                                .Select(s => s.MyOfficeId).FirstOrDefault();
                            parcel.DeliverToOfficeId = deliveryToOffice;
                        }
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.BeForwarding;
                        _parcelRepository.Update(parcel);
                    }
                    return Json(true);
                }
            }

            return Json(false);
        }

        [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
        public ActionResult DownloadParcelPackaging(int id)
        {
            var fileName = string.Format("BuuPhamDongGoiChuyenTiep_{0}", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
            return PdfResult(_parcelDeliveryService.DownloadParcelPackaging(id, WorkContext.MyOfficeId), fileName);
        }

        #endregion

        #region Bưu Phẩm Đến Bưu Cục

        public ActionResult ComePostOffices()
        {
            return View();
        }

        [GridAction]
        public ActionResult ComePostOfficesGridModel(string search)
        {
            if (!string.IsNullOrEmpty(search))
            {
                var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == search);
                //Nếu bưu phẩm ở trạng thái Đang Chuyển Tiếp
                //Là bưu phẩm chuyển đến bưu cục khác (parcel.DeliverToOfficeId == WorkContext.MyOfficeId)
                //Không nằm trong bưu cục mình đang làm việc (parcel.MyOfficeId != WorkContext.MyOfficeId))
                if (parcel != null && parcel.Status == (int)TrackingStatus.EnumTrackingStatus.BeForwarding 
                    && parcel.DeliverToOfficeId == WorkContext.MyOfficeId
                    && parcel.MyOfficeId != WorkContext.MyOfficeId)
                {
                    var myProvince = _stateProvinceRepository.Search("").FirstOrDefault(p => p.IsMain && p.MyOfficeId == WorkContext.MyOfficeId);
                    var tracking = new Tracking
                    {
                        CreateDate = DateTime.Now,
                        DateOfSending = DateTime.Now,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId,
                        StateProvinceId = myProvince.StateProvinceId,
                        Status = (int)TrackingStatus.EnumTrackingStatus.ComePostOffices,
                        UserId = WorkContext.CurrentUserId
                    };
                    using (UnitOfWork)
                    {
                        _trackingRepository.Insert(tracking);
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.ComePostOffices;
                        _parcelRepository.Update(parcel);
                    }
                }
            }
            //Chỉ hiển thị bưu phẩm chuyển đến (x.DeliverToOfficeId == WorkContext.MyOfficeId)
            //Không hiển thị bưu phẩm nếu cùng trong bưu cục (x.MyOfficeId != WorkContext.MyOfficeId)
            var query = from x in Repository.GetAll().Include(p => p.Customer)
                        join o in _stateProvinceRepository.GetAll() on x.DeliverFromId equals o.StateProvinceId
                        join p in _stateProvinceRepository.GetAll() on x.DeliverToId equals p.StateProvinceId
                        join r in _stateProvinceBelongToRegionRepository.GetAll().Include(p => p.Region) on x.DeliverToId equals r.StateProvinceId
                        where x.DeliverToOfficeId == WorkContext.MyOfficeId && x.MyOfficeId != WorkContext.MyOfficeId
                        && r.MyOfficeId == WorkContext.MyOfficeId
                        && x.Trackings.All(t => t.Status != (int)TrackingStatus.EnumTrackingStatus.ComePostOffices)
                        && x.Status == (int)TrackingStatus.EnumTrackingStatus.BeForwarding
                        && !x.IsEms
                        orderby x.ParcelId descending
                        select new ParcelModel
                        {
                            ParcelId = x.ParcelId,
                            TrackingNumbers = x.TrackingNumbers,
                            CustomerId = x.CustomerId,
                            CustomerName = x.Customer.CustomerShortName,
                            DateOfSending = EntityFunctions.TruncateTime(x.DateOfSending).Value,
                            DeliverToName = p.StateProvinceName,
                            DeliverFromName = o.StateProvinceName,
                            RegionName = r.Region.RegionName,
                            IsEms = x.IsEms,
                            ToAddress = x.ToAddress,
                            TotalCost = x.PaymentType == (int)PaymentTypes.EnumPaymentTypes.Collection ? x.TotalCost : 0,
                            Note = x.Note
                        };
            var gridModel = new GridModel<ParcelModel>
            {
                Data = query
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        #endregion
    }
}
